package com.uuj.dome;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.uuj.dome.bean.LoggerEntity;
import com.uuj.dome.jpa.LoggerJpa;
import com.uuj.dome.utils.LoggerUtil;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * ClassName:LoggerInterceptor
 * PACKAGE_NAME:com.uuj.dome
 */
public class LoggerInterceptor implements HandlerInterceptor {

    // 请求开始时间标识
    private static final String LOGGER_SEND_TIME = "_send_time";
    // 请求日志实体标识
    private static final String LOGGER_ENTITY = "_logger_entity";

    /**
     * 进入springmvc的controller之前开始记录日志实体
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  对象
     * @return 返回值
     * @throws Exception 异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 创建日志实体
        LoggerEntity entity = new LoggerEntity();
        // 获取请求sessionId
        String sessionId = request.getRequestedSessionId();
        // 请求路径
        String uri = request.getRequestURI();
        // 获取请求参数信息
        String paramData = JSON.toJSONString(request.getParameterMap(),
                SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullStringAsEmpty);
        // 设置请求客户端ip
        entity.setClientIp(LoggerUtil.getCliectIp(request));
        // 设置请求方法
        entity.setMethod(request.getMethod());
        // 设置请求类型
        entity.setType(LoggerUtil.getRequestType(request));
        // 设置请求参数内容
        entity.setParamData(paramData);
        // 设置请求地址
        entity.setUri(uri);
        // 设置sessionId
        entity.setSessionId(sessionId);
        // 请求开始的时间
        request.setAttribute(LOGGER_SEND_TIME, System.currentTimeMillis());
        // 设置请求实体到request 方便afterCompletion方法调用
        request.setAttribute(LOGGER_ENTITY, entity);

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 获取请求错误码
        int status = response.getStatus();
        // 当前时间
        long currentTimeMillis = System.currentTimeMillis();
        // 请求开始时间
        Long time = Long.valueOf(request.getAttribute(LOGGER_SEND_TIME).toString());
        // 获取本次请求日志实体类
        LoggerEntity entity = (LoggerEntity) request.getAttribute(LOGGER_ENTITY);
        // 请求时间差
        entity.setTimeConsuming(Integer.valueOf((currentTimeMillis - time) + ""));
        // 设置返回时间
        entity.setReturnTime(currentTimeMillis + "");
        // 设置返回错误码
        entity.setHttpStatusCode(status + "");
        // 设置返回值
        entity.setReturnData(JSON.toJSONString(request.getAttribute(LOGGER_ENTITY),
                SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullStringAsEmpty));
        // 执行将日志写入数据库
        LoggerJpa dao = getDAO(LoggerJpa.class, request);
        dao.save(entity);

    }

    /**
     * 根据传入类型获取spring管理对应的dao
     *
     * @param clazz   类型
     * @param request 请求对象
     * @return 返回dao
     */
    private <T> T getDAO(Class<T> clazz, HttpServletRequest request) {

        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return factory.getBean(clazz);
    }
}
